------------Spelling Mastery-----------
A 4am crack                  2017-10-20
---------------------------------------

Name: Spelling Mastery
Genre: educational
Year: 1988
Credits: Ahead Designs
Publisher: Developmental Learning
  Materials, Inc.
Platform: Apple ][+ or later
Media: single-sided 5.25-inch floppy
OS: Pronto-DOS
Previous cracks: none
Similar cracks:
  #460 Curious George Visits The
       Library
  #185 Curious George in Outer Space
  #008 Curious George Goes Shopping

                   ~

COPYA
  no errors, but copy displays a
  graphical error message "File not
  found, press C when you have
  corrected the problem"

Locksmith Fast Disk Backup
  ditto

EDD 4 bit copy (no sync, no count)
  ditto

Copy ][+ nibble editor
  nothing suspicious

Disk Fixer
  standard DOS 3.3-shaped bootloader
    (Pronto-DOS)
  disk catalog on track $11
  T01,S07 -> startup program is "HELLO"

Why didn't any of my copies work?
  Probably a sneaky runtime protection
  check somewhere that flips a bit and
  triggers a spurious "file not found"
  message to confuse me.

Next steps:

  1. Search for common signs of a
     runtime protection check
  2. If that fails, trace the startup
     program
  3. If that fails, I dunno, go feed
     the ducks or something?

                   ~

Turning to my Disk Fixer sector editor,
I search the disk for the most common
indicator of a protection check: the
soft switch that turns on the drive
motor.

[Disk Fixer]
  ["F"ind]
    ["H"ex]
      "BD 89 C0"

                 --v--

------------- DISK SEARCH -------------

$00/$07-$4F   $14/$0E-$C3


             PRESS [RETURN]

                 --^--

The match on track $00 is part of the
RWTS, i.e. legitimate. The match on
track $14 immediately suspicious.
Copy II Plus "disk map" tells me this
sector is part of the "START" file, so
let's look there.

[S6,D1=non-working copy]

]PR#6
...<Ctrl-C>...

]LIST

 10  ONERR  GOTO 100
 20  POKE 1012,0
 30  HGR2
 35  PRINT "MAXFILES 1"
 40  PRINT "BLOAD START"
 50  PRINT "BRUN MENU"
 100  CALL  - 1438

]BLOAD START
]CALL -151

*AA72.AA73

AA72- 00 60

Scanning memory, I find the suspicious
command at $61BF, in a routine that
appears to start at $61AF.

*61AFL

61AF-   A9 60       LDA   #$60
61B1-   8D 88 62    STA   $6288
61B4-   A9 05       LDA   #$05
61B6-   8D 89 62    STA   $6289

; turn on drive motor manually
61B9-   AE 88 62    LDX   $6288
61BC-   BD 8E C0    LDA   $C08E,X
61BF-   BD 89 C0    LDA   $C089,X

; wait for drive to spin up
61C2-   A9 00       LDA   #$00
61C4-   8D 8A 62    STA   $628A
61C7-   A0 00       LDY   #$00
61C9-   C8          INY
61CA-   D0 FD       BNE   $61C9
61CC-   EE 8A 62    INC   $628A
61CF-   D0 F6       BNE   $61C7

61D1-   A9 00       LDA   #$00
61D3-   8C 8A 62    STY   $628A
61D6-   20 7C 62    JSR   $627C

*627CL

; get a disk nibble
627C-   BD 8C C0    LDA   $C08C,X
627F-   10 FB       BPL   $627C
6281-   60          RTS

; Y and $628A both start at 0, so this
; will look a loooong time for the
; expected nibbles, but not forever
61D9-   C8          INY
61DA-   D0 08       BNE   $61E4
61DC-   EE 8A 62    INC   $628A
61DF-   D0 03       BNE   $61E4
61E1-   4C 77 62    JMP   $6277

; execution continues here (from $61DA
; or $61DF)
; find a nibble sequence, $D5 $AA $BB
61E4-   C9 D5       CMP   #$D5
61E6-   D0 EE       BNE   $61D6
61E8-   20 7C 62    JSR   $627C
61EB-   C9 AA       CMP   #$AA
61ED-   D0 F5       BNE   $61E4
61EF-   20 7C 62    JSR   $627C
61F2-   C9 BB       CMP   #$BB
61F4-   D0 EE       BNE   $61E4

; capture several 4-4 encoded values
; (like an address field?)
61F6-   A0 00       LDY   #$00
61F8-   20 7C 62    JSR   $627C
61FB-   38          SEC
61FC-   2A          ROL
61FD-   8D 8A 62    STA   $628A
6200-   20 7C 62    JSR   $627C
6203-   2D 8A 62    AND   $628A
6206-   99 8B 62    STA   $628B,Y
6209-   C8          INY
620A-   C0 02       CPY   #$02
620C-   D0 EA       BNE   $61F8

; skip over 4 nibbles
620E-   A0 00       LDY   #$00
6210-   20 7C 62    JSR   $627C
6213-   C8          INY
6214-   C0 04       CPY   #$04
6216-   D0 F8       BNE   $6210

; skip over sync nibbles ($FF)
6218-   BD 8C C0    LDA   $C08C,X
621B-   10 FB       BPL   $6218
621D-   C9 FF       CMP   #$FF
621F-   D0 4E       BNE   $626F

; reset data latch
6221-   BD 8D C0    LDA   $C08D,X

; kill some time to get out of sync
; with the "proper" start of nibbles)
6224-   A0 10       LDY   #$10
6226-   A5 09       LDA   $09

; now start looking for nibbles that
; don't really exist (except they do,
; because we're out of sync and reading
; timing bits as data)
6228-   BD 8C C0    LDA   $C08C,X
622B-   10 FB       BPL   $6228
622D-   88          DEY
622E-   F0 3F       BEQ   $626F

; find a desynchronized $EE nibble
6230-   C9 EE       CMP   #$EE
6232-   D0 F4       BNE   $6228

; store next 4 desynchronized nibbles
6234-   A0 00       LDY   #$00
6236-   BD 8C C0    LDA   $C08C,X
6239-   10 FB       BPL   $6236
623B-   99 8D 62    STA   $628D,Y
623E-   C8          INY
623F-   C0 04       CPY   #$04
6241-   D0 F3       BNE   $6236

; check 4-and-4 encoded values that we
; captured earlier
6243-   AD 8B 62    LDA   $628B
6246-   CD 82 62    CMP   $6282
6249-   D0 24       BNE   $626F
624B-   AD 8C 62    LDA   $628C
624E-   CD 83 62    CMP   $6283
6251-   D0 1C       BNE   $626F

; check desynchronized nibbles that we
; captured earlier against an encrypted
; array at $6284
6253-   A0 00       LDY   #$00
6255-   B9 8D 62    LDA   $628D,Y
6258-   49 87       EOR   #$87
625A-   38          SEC
625B-   E9 01       SBC   #$01
625D-   D9 84 62    CMP   $6284,Y
6260-   D0 0D       BNE   $626F
6262-   99 8D 62    STA   $628D,Y
6265-   C8          INY
6266-   C0 04       CPY   #$04
6268-   D0 EB       BNE   $6255

; if everything checks out, execution
; falls through to here -- turn off the
; drive motor, clear the carry bit, and
; exit gracefully
626A-   BD 88 C0    LDA   $C088,X
626D-   18          CLC
626E-   60          RTS

; any failures end up here -- decrement
; the death counter and eventually give
; up
626F-   CE 89 62    DEC   $6289
6272-   F0 03       BEQ   $6277
6274-   4C D1 61    JMP   $61D1

; turn off drive, set carry, and exit
6277-   BD 88 C0    LDA   $C088,X
627A-   38          SEC
627B-   60          RTS

                   ~

Interesting to note: there is no track
seek at the beginning of this routine.
It just assumes it's on the right track
to find the magic protection bitstream.
Turning back to the Copy II Plus nibble
editor, I can see the $D5 $AA $BB
nibble sequence on every single track,
followed by the magic bitstream and
desynchronized values. So this disk is
always ready to verify its originality,
regardless of which track it's on.

The caller only cares about the carry
bit, so let's just clear the carry bit
at $61AF and exit unconditionally.

T14,S0E,$B3: A9 -> 18

Quod erat liberandum.

---------------------------------------
A 4am crack                    No. 1481
------------------EOF------------------
